﻿using System;
using System.Linq;
using System.IO;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Framework.Client;
using Microsoft.LightSwitch.Presentation;
using Microsoft.LightSwitch.Presentation.Extensions;
using Microsoft.LightSwitch.Framework;
using LightSwitchApplication.UserCode;
using System.Globalization;
using System.Windows.Controls;

namespace LightSwitchApplication
{
    public partial class Attendance
    {
        private DateTime dtGroupStartLast;
        private bool firstInitPassed = false;

        private TabControl tabControl;
        private bool activeErrorProviderCreation;

        partial void Attendance_Created()
        {
            this.FindControl("tabTime").ControlAvailable += tabControl_ControlAvailable;
        }

        void tabControl_ControlAvailable(object sender, ControlAvailableEventArgs e)
        {
            tabControl = (TabControl)e.Control;
            tabControl.SelectionChanged += tabControl_SelectionChanged;
        }

        void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {            
            if (tabControl.SelectedIndex == 1)
                activeErrorProviderCreation = true;
            else
                activeErrorProviderCreation = false;
        }

        partial void dtGroupStart_Validate(ScreenValidationResultsBuilder results)
        {
            // results.AddPropertyError("<Fehlermeldung>");
            if (this.tlTraingroupSet.SelectedItem == null)
                return;

            if (bolIntervalOverride)
                return;
            
            if(!activeErrorProviderCreation)
                return;

            if (this.tlTraingroupSet.SelectedItem.TimeFrom.TimeOfDay != dtGroupStart.TimeOfDay)
                results.AddPropertyError("Startzeit entspricht nicht der Voreinstellung für die Trainingsgruppe!");

            ValidateTraingroupDay(this.tlTraingroupSet.SelectedItem, dtGroupStart, results);

            DeactivateCreateTrainsessionOnError();
        }

        partial void dtGroupEnd_Validate(ScreenValidationResultsBuilder results)
        {
            // results.AddPropertyError("<Fehlermeldung>");
            if (dtGroupEnd < dtGroupStart)
                results.AddPropertyError("Gruppenstart muss vor dem Ende liegen.");

            if (this.tlTraingroupSet.SelectedItem == null)
                return;

            if (bolIntervalOverride)
                return;

            if (!activeErrorProviderCreation)
                return;

            if (this.tlTraingroupSet.SelectedItem.TimeTo.TimeOfDay != dtGroupEnd.TimeOfDay)
                results.AddPropertyError("Endzeit entspricht nicht der Voreinstellung für die Trainingsgruppe!");

            ValidateTraingroupDay(this.tlTraingroupSet.SelectedItem, dtGroupEnd, results);

            DeactivateCreateTrainsessionOnError();
        }

        partial void dtGroupStart_Changed()
        {
            if (!firstInitPassed)
            {
                dtGroupStartLast = dtGroupStart;
                firstInitPassed = true;
                return;
            }

            if (dtGroupStart == dtGroupStartLast)
                return;

            TimeSpan changeDelta = dtGroupStart.Subtract(dtGroupStartLast);
            dtGroupEnd = dtGroupEnd.Add(changeDelta);

            dtGroupStartLast = dtGroupStart;
        }

        partial void tlTraingroupSet_SelectionChanged()
        {
            if (this.tlTraingroupSet.SelectedItem == null)
                return;

            dtGroupStart = SyncedTimeOfDay(dtGroupStart, this.tlTraingroupSet.SelectedItem.TimeFrom);
            dtGroupEnd = SyncedTimeOfDay(dtGroupEnd, this.tlTraingroupSet.SelectedItem.TimeTo);
        }

        private DateTime SyncedTimeOfDay(DateTime DatePart, DateTime TimeOfDayPart)
        {
            TimeSpan ts = new TimeSpan(TimeOfDayPart.Hour, TimeOfDayPart.Minute, TimeOfDayPart.Second);
            return DatePart.Date + ts;
        }

        partial void CreateTrainsession_Execute()
        {
            ServerJobFactory job = new ServerJobFactory(this.DataWorkspace.ApplicationData);
            job.CreateJob("CreateTrainsession");

            CultureInfo culture = new CultureInfo("de-DE");

            job.AddParameter("Start", dtGroupStart.ToString(culture));
            job.AddParameter("End", dtGroupEnd.ToString(culture));
            job.AddParameter("IntervalOverride", bolIntervalOverride.ToString());
            job.AddParameter("TraingroupId", this.tlTraingroupSet.SelectedItem.Id.ToString());

            job.SaveJob();

            this.tbTrainsessionCollection.Refresh();
            tbTrainsession current = this.tbTrainsessionCollection.Where(s => s.GroupStart == dtGroupStart).FirstOrDefault();
            this.tbTrainsessionCollection.SelectedItem = current;
        }

        private void ValidateTraingroupDay(tlTraingroup Traingroup, DateTime Day, ScreenValidationResultsBuilder results)
        {
            if (Traingroup.trIntervalValueTraingroupSetItem.FirstOrDefault() == null)
                return;

            tlInterval currentInterval = Traingroup.trIntervalValueTraingroupSetItem.FirstOrDefault().tlIntervalValue.tlInterval;

            switch (currentInterval.StaticId)
            {
                case 1: // Wöchentlich
                    if (!ValidWeeklyInterval(Traingroup.trIntervalValueTraingroupSetItem, Day))
                        results.AddPropertyError("Wöchentliches Intervall: Ausgewähltes Datum nicht möglich.");
                    break;
                case 2: // Monatlich
                    if (!ValidMonthlyInterval(Traingroup.trIntervalValueTraingroupSetItem, Day))
                        results.AddPropertyError("Monatliches Intervall: Ausgewähltes Datum nicht möglich.");
                    break;
                default: // Unbekannt
                    results.AddPropertyError("Unbekanntes Intervall: Training kann nur mit bekannten Intervallen angelegt werden.");
                    break;
            }
        }

        private bool ValidMonthlyInterval(EntityCollection<trIntervalValueTraingroupSetItem> SelectedIntervals, DateTime Day)
        {
            foreach (trIntervalValueTraingroupSetItem element in SelectedIntervals)
            {
                tlIntervalValue intervalValue = element.tlIntervalValue;
                if (intervalValue.Value != Day.Day)
                    return false;
            }

            return true;
        }

        private bool ValidWeeklyInterval(EntityCollection<trIntervalValueTraingroupSetItem> SelectedIntervals, DateTime Day)
        {
            DayOfWeek? validDay = null;
            foreach (trIntervalValueTraingroupSetItem element in SelectedIntervals)
            {
                tlIntervalValue intervalValue = element.tlIntervalValue;
                switch (intervalValue.Value)
                {
                    case 1: // Montag
                        validDay = DayOfWeek.Monday;
                        break;
                    case 2: // Dienstag
                        validDay = DayOfWeek.Tuesday;
                        break;
                    case 3: // Mittwoch
                        validDay = DayOfWeek.Wednesday;
                        break;
                    case 4: // Donnerstag
                        validDay = DayOfWeek.Thursday;
                        break;
                    case 5: // Freitag
                        validDay = DayOfWeek.Friday;
                        break;
                    case 6: // Samstag
                        validDay = DayOfWeek.Saturday;
                        break;
                    case 7: // Sonntag
                        validDay = DayOfWeek.Sunday;
                        break;
                }
                if (validDay == Day.DayOfWeek)
                    return true;
            }
            return false;
        }

        private void DeactivateCreateTrainsessionOnError()
        {
            if (this.Details.ValidationResults.HasErrors)
                this.FindControl("btCreateTrainsession").IsEnabled = false;
            else
                this.FindControl("btCreateTrainsession").IsEnabled = true;
        }

    }
}
